#include <SDL/SDL.h>

struct {
  int downcode, upcode;
} SDLK2scancode_map[SDLK_LAST] = {
    [SDLK_ESCAPE] = {0x76, 0xF076},
    [SDLK_F1] = {0x05, 0xF005},
    [SDLK_F2] = {0x06, 0xF006},
    [SDLK_F3] = {0x04, 0xF004},
    [SDLK_F4] = {0x0C, 0xF00C},
    [SDLK_F5] = {0x03, 0xF003},
    [SDLK_F6] = {0x0B, 0xF00B},
    [SDLK_F7] = {0x83, 0xF083},
    [SDLK_F8] = {0x0A, 0xF00A},
    [SDLK_F9] = {0x01, 0xF001},
    [SDLK_F10] = {0x09, 0xF009},
    [SDLK_F11] = {0x78, 0xF078},
    [SDLK_F12] = {0x07, 0xF007},
    [SDLK_SCROLLOCK] = {0x7E, 0xF07E},
    [SDLK_BACKQUOTE] = {0x0E, 0xF00E},
    [SDLK_1] = {0x16, 0xF016},
    [SDLK_2] = {0x1E, 0xF01E},
    [SDLK_3] = {0x26, 0xF026},
    [SDLK_4] = {0x25, 0xF025},
    [SDLK_5] = {0x2E, 0xF02E},
    [SDLK_6] = {0x36, 0xF036},
    [SDLK_7] = {0x3D, 0xF03D},
    [SDLK_8] = {0x3E, 0xF03E},
    [SDLK_9] = {0x46, 0xF046},
    [SDLK_0] = {0x45, 0xF045},
    [SDLK_MINUS] = {0x4E, 0xF04E},
    [SDLK_EQUALS] = {0x55, 0xF055},
    [SDLK_BACKSPACE] = {0x66, 0xF066},
    [SDLK_TAB] = {0x0D, 0xF00D},
    [SDLK_q] = {0x15, 0xF015},
    [SDLK_w] = {0x1D, 0xF01D},
    [SDLK_e] = {0x24, 0xF024},
    [SDLK_r] = {0x2D, 0xF02D},
    [SDLK_t] = {0x2C, 0xF02C},
    [SDLK_y] = {0x35, 0xF035},
    [SDLK_u] = {0x3C, 0xF03C},
    [SDLK_i] = {0x43, 0xF043},
    [SDLK_o] = {0x44, 0xF044},
    [SDLK_p] = {0x4D, 0xF04D},
    [SDLK_LEFTBRACKET] = {0x54, 0xF054},
    [SDLK_RIGHTBRACKET] = {0x5B, 0xF05B},
    [SDLK_SLASH] = {0x5D, 0xF05D},
    [SDLK_CAPSLOCK] = {0x58, 0xF058},
    [SDLK_a] = {0x1C, 0xF01C},
    [SDLK_s] = {0x1B, 0xF01B},
    [SDLK_d] = {0x23, 0xF023},
    [SDLK_f] = {0x2B, 0xF02B},
    [SDLK_g] = {0x34, 0xF034},
    [SDLK_h] = {0x33, 0xF033},
    [SDLK_j] = {0x3B, 0xF03B},
    [SDLK_k] = {0x42, 0xF042},
    [SDLK_l] = {0x4B, 0xF04B},
    [SDLK_SEMICOLON] = {0x4C, 0xF04C},
    [SDLK_QUOTE] = {0x52, 0xF052},
    [SDLK_RETURN] = {0x5A, 0xF05A},
    [SDLK_LSHIFT] = {0x12, 0xF012},
    [SDLK_z] = {0x1A, 0xF01A},
    [SDLK_x] = {0x22, 0xF022},
    [SDLK_c] = {0x21, 0xF021},
    [SDLK_v] = {0x2A, 0xF02A},
    [SDLK_b] = {0x32, 0xF032},
    [SDLK_n] = {0x31, 0xF031},
    [SDLK_m] = {0x3A, 0xF03A},
    [SDLK_COMMA] = {0x41, 0xF041},
    [SDLK_PERIOD] = {0x49, 0xF049},
    [SDLK_BACKSLASH] = {0x4A, 0xF04A},
    [SDLK_RSHIFT] = {0x59, 0xF059},
    [SDLK_LCTRL] = {0x14, 0xF014},
    [SDLK_LALT] = {0x11, 0xF011},
    [SDLK_SPACE] = {0x29, 0xF029},
    [SDLK_RALT] = {0xE011, 0xE0F011},
    [SDLK_RCTRL] = {0xE014, 0xE0F014},
    [SDLK_INSERT] = {0xE070, 0xE0F070},
    [SDLK_HOME] = {0xE06C, 0xE0F06C},
    [SDLK_PAGEUP] = {0xE07D, 0xE0F07D},
    [SDLK_DELETE] = {0xE071, 0xE0F071},
    [SDLK_END] = {0xE069, 0xE0F069},
    [SDLK_PAGEDOWN] = {0xE07A, 0xE0F07A},
    [SDLK_UP] = {0xE075, 0xE0F075},
    [SDLK_LEFT] = {0xE06B, 0xE0F06B},
    [SDLK_DOWN] = {0xE072, 0xE0F072},
    [SDLK_RIGHT] = {0xE074, 0xE0F074},
    [SDLK_NUMLOCK] = {0x77, 0xF077},
    [SDLK_KP_DIVIDE] = {0xE04A, 0xE0F04A},
    [SDLK_KP_MULTIPLY] = {0x7C, 0xF07C},
    [SDLK_KP_MINUS] = {0x7B, 0xF07B},
    [SDLK_KP_PLUS] = {0x79, 0xF079},
    [SDLK_KP7] = {0x6C, 0xF06C},
    [SDLK_KP8] = {0x75, 0xF075},
    [SDLK_KP9] = {0x7D, 0xF07D},
    [SDLK_KP4] = {0x6B, 0xF06B},
    [SDLK_KP5] = {0x73, 0xF073},
    [SDLK_KP6] = {0x74, 0xF074},
    [SDLK_KP1] = {0x69, 0xF069},
    [SDLK_KP2] = {0x72, 0xF072},
    [SDLK_KP3] = {0x7A, 0xF07A},
    [SDLK_KP0] = {0x70, 0xF070},
    [SDLK_KP_EQUALS] = {0x71, 0xF071},
    [SDLK_KP_ENTER] = {0xE05A, 0xE0F05A},
};

uint32_t SDLKey_to_scancode(SDL_EventType type, SDLKey key) {
  if (key < 0 || key >= SDLK_LAST) return 0;
  uint32_t scancode = type == SDL_KEYUP ? SDLK2scancode_map[key].upcode
                                        : SDLK2scancode_map[key].downcode;

  return scancode;
}

// wait to be completed
const char *SDLK2ascii_map[SDLK_LAST] = {
    [SDLK_ESCAPE] = "\e",
    [SDLK_F1] = "\eOP",
    [SDLK_F2] = "\eOQ",
    [SDLK_F3] = "\eOR",
    [SDLK_F4] = "\eOS",
    [SDLK_F5] = "\e[15~",
    [SDLK_F6] = "\e[17~",
    [SDLK_F7] = "\e[18~",
    [SDLK_F8] = "\e[19~",
    [SDLK_F9] = "\e[20~",
    [SDLK_F10] = "\e[21~",
    [SDLK_F11] = "\e[22~",
    [SDLK_F12] = "\e[24~",
    [SDLK_BACKQUOTE] = "`",
    [SDLK_1] = "1",
    [SDLK_2] = "2",
    [SDLK_3] = "3",
    [SDLK_4] = "4",
    [SDLK_5] = "5",
    [SDLK_6] = "6",
    [SDLK_7] = "7",
    [SDLK_8] = "8",
    [SDLK_9] = "9",
    [SDLK_0] = "0",
    [SDLK_MINUS] = "-",
    [SDLK_EQUALS] = "=",
    [SDLK_BACKSPACE] = "\x8",
    [SDLK_TAB] = "\t",
    [SDLK_q] = "q",
    [SDLK_w] = "w",
    [SDLK_e] = "e",
    [SDLK_r] = "r",
    [SDLK_t] = "t",
    [SDLK_y] = "y",
    [SDLK_u] = "u",
    [SDLK_i] = "i",
    [SDLK_o] = "o",
    [SDLK_p] = "p",
    [SDLK_LEFTBRACKET] = "{",
    [SDLK_RIGHTBRACKET] = "}",
    [SDLK_SLASH] = "/",
    [SDLK_a] = "a",
    [SDLK_s] = "s",
    [SDLK_d] = "d",
    [SDLK_f] = "f",
    [SDLK_g] = "g",
    [SDLK_h] = "h",
    [SDLK_j] = "j",
    [SDLK_k] = "k",
    [SDLK_l] = "l",
    [SDLK_SEMICOLON] = ";",
    [SDLK_QUOTE] = "'",
    [SDLK_RETURN] = "\n",
    [SDLK_LSHIFT] = "", // cannot be escaped
    [SDLK_z] = "z",
    [SDLK_x] = "x",
    [SDLK_c] = "c",
    [SDLK_v] = "v",
    [SDLK_b] = "b",
    [SDLK_n] = "n",
    [SDLK_m] = "m",
    [SDLK_COMMA] = ",",
    [SDLK_PERIOD] = ".",
    [SDLK_BACKSLASH] = "\\",
    [SDLK_RSHIFT] = "",   // cannot be escaped
    [SDLK_LCTRL] = "\eD", // cannot be escaped
    [SDLK_LALT] = "",     // cannot be escaped
    [SDLK_SPACE] = " ",
    [SDLK_RALT] = "",  // cannot be escaped
    [SDLK_RCTRL] = "", // cannot be escaped
    [SDLK_INSERT] = "\e[2~",
    [SDLK_HOME] = "\e[1~",
    [SDLK_PAGEUP] = "\e[5~",
    [SDLK_DELETE] = "\x7f",
    [SDLK_END] = "\e[4~",
    [SDLK_PAGEDOWN] = "\e[6~",
    [SDLK_UP] = "\e[A",
    [SDLK_LEFT] = "\e[D",
    [SDLK_DOWN] = "\e[B",
    [SDLK_RIGHT] = "\e[C",
    [SDLK_KP_DIVIDE] = "/",
    [SDLK_KP_MULTIPLY] = "*",
    [SDLK_KP_MINUS] = "-",
    [SDLK_KP_PLUS] = "+",
    [SDLK_KP7] = "7",
    [SDLK_KP8] = "8",
    [SDLK_KP9] = "9",
    [SDLK_KP4] = "4",
    [SDLK_KP5] = "5",
    [SDLK_KP6] = "6",
    [SDLK_KP1] = "1",
    [SDLK_KP2] = "2",
    [SDLK_KP3] = "3",
    [SDLK_KP0] = "0",
    [SDLK_KP_EQUALS] = "=",
    [SDLK_KP_ENTER] = "\n",
    [SDLK_KP_PERIOD] = ".",
};

const char *SDLKey_to_ascii(SDL_EventType type, SDLKey key) {
  if (key < 0 || key >= SDLK_LAST) return "";
  return SDLK2ascii_map[key];
}
